import Vue from 'vue'
import HTML5History from '../myroute/html5History'
import HashHistory from '../myroute/hashHistory'
let _Vue = null
export default class VueRouter {
  static install () {
    // 1 判断当前插件是否已经被安装， 安装过就不在安装
    if (VueRouter.install.installed) {
      return
    }
    VueRouter.install.installed = true // installed 记录安装过
    // 2 把Vue的构造啊何时农户记录到全局变量， 因为将来需要在Vue 实例中使用Vue的构造函数例如注册组件等
    _Vue = Vue
    // 3、 吧创建Vue实例是后传入的router对象注入到Vue 实例上
    // _Vue.prototype.$router = this.$router.options
    // 混入
    _Vue.mixin({
      beforeCreate () {
        // 组件不执行， Vue实例不执行
        if (this.$options.router) { // 只有Vue实例才有$options.router属性，组件是没有的router的， 组件不执行
          _Vue.prototype.$router = this.$options.router // 只需要执行一次
          this.$router.init() // 注册组件
        }
      }
    })
  }

  constructor (options) {
    this.options = options
    this.routeMap = {} // 记录键值对, 路由规则转换成path --> compontents
    this.judgeModel()
    // this.data = _Vue.observable({
    //   current: '/'
    // })

    // 响应式对象, 存储当前的路由对象
  }

  /**
   * 判断模式
   */
  judgeModel () {
    const mode = this.options.mode || 'hash'
    switch (mode) {
      case 'history':
        this.history = new HTML5History(this, _Vue)
        break
      case 'hash':
        this.history = new HashHistory(this, _Vue)
        break
    }
  }

  init () {
    this.createRouteMap()
    this.initComponent(_Vue)
    this.history.setupListener()
  }

  /**
   * 遍历所有的路由规则， 把路由规则解析成键值对， 存放到routeMap中
   */
  createRouteMap () {
    this.options.routes.forEach(route => {
      this.routeMap[route.path] = route.component
    })
  }

  /**
   * 创建组件 router-link
   * @param {} Vue
   */
  initComponent (Vue) {
    const self = this
    Vue.component('router-link', {
      props: {
        to: String
      },
      /**
       * 渲染函数, 在没有编译器的时候， 需要我们自己写render函数
       * h : 创建虚拟DOM,
       * @param {*} h
       * return 返回h 创建的虚拟DOM
       */
      render (h) {
        return h('a', {
          attrs: {
            href: this.to
          },
          on: {
            click: (e) => {
              self.history.clickHander(e, this.to)
            }
          }
        }, [this.$slots.default])
      },
      methods: {
      }
      // template: '<a :href="to"><slot></slot></a>' // 运行时版本的vue缺少编译器，编译器的作用就是把templete转换成render函数， 所以不能支持template,
    })

    Vue.component('router-view', {
      /**
       * 当current 发生变化时， 组件自动更新
       * @param {*} h
       * @return {*}
       */
      render (h) {
        const path = self.data.current // 获取当前地址， data是响应式的， 发生改变， 会自动更新
        const compnent = self.routeMap[path] // 获取路径对应的组件
        return h(compnent)
      }
    })
  }
}
